package chatrooms

import (
	"context"
	"dash/categories"
	"dash/watch"
	"github.com/go-kit/kit/log"
)

type ChatroomService interface {
	Card(ctx context.Context, id, uid string) (*ChatroomCardResponse, error)
	Detail(ctx context.Context, id, uid string) (*ChatroomDetailResponse, error)
	UpdateComment(ctx context.Context, id, comment string) error
	UpdateTags(ctx context.Context, id string, tags []string) error
	UpdateCategory(ctx context.Context, id, categoryId string) ([]string, error)
	UpdateWatched(ctx context.Context, id string, watched bool) error
}

type ChatroomCount struct {
	MemberCount          int64 `json:"memberCount"`
	MessageCount7        int64 `json:"messageCount7"`
	AlarmCount7          int64 `json:"alarmCount7"`
	LastMessageTimestamp int64 `json:"lastMessageTimestamp"`
}

type defaultChatroomService struct {
	repo                    ChatroomRepository
	logger                  log.Logger
	categorySvc             categories.CategoryService
	chatroomWatchRepository watch.WatchRepository
}

func (svc *defaultChatroomService) UpdateComment(ctx context.Context, id, comment string) error {
	_, err := svc.repo.Get(ctx, id)
	if err != nil {
		_ = svc.logger.Log("err", err)
		return NoIdErr
	}
	err = svc.repo.UpdateComment(ctx, id, comment)
	if err != nil {
		return UpdateErr
	}
	return nil
}

func (svc *defaultChatroomService) UpdateTags(ctx context.Context, id string, tags []string) error {
	_, err := svc.repo.Get(ctx, id)
	if err != nil {
		return NoIdErr
	}
	err = svc.repo.UpdateTags(ctx, id, tags)
	if err != nil {
		return UpdateErr
	}
	return nil
}

func (svc *defaultChatroomService) UpdateCategory(ctx context.Context, id, categoryId string) ([]string, error) {
	if len(id) <= 0 {
		return nil, NoIdErr
	}
	_, err := svc.repo.Get(ctx, id)
	if err != nil {
		return nil, NoIdErr
	}
	err = svc.repo.UpdateCategory(ctx, id, categoryId)
	if err != nil {
		return nil, err
	}
	categoryIds, err := svc.categorySvc.GetChatroomCategoryIds(ctx, categoryId)
	if err != nil {
		_ = svc.logger.Log("err", err)
	}
	return categoryIds, nil
}

func (svc *defaultChatroomService) UpdateWatched(ctx context.Context, id string, watched bool) error {
	_, err := svc.repo.Get(ctx, id)
	if err != nil {
		return NoIdErr
	}
	err = svc.repo.UpdateWatched(ctx, id, watched)
	if err != nil {
		return UpdateErr
	}
	return nil
}

func (svc *defaultChatroomService) Card(ctx context.Context, id, userId string) (*ChatroomCardResponse, error) {
	chatroom, err := svc.repo.Get(ctx, id)
	if err != nil {
		return nil, NoIdErr
	}
	watched, err := svc.chatroomWatchRepository.GetChatroomWatchedStatus(ctx, id, userId)
	if err != nil {
		_ = svc.logger.Log("get chatroom watched error,chatroom id:", id)
	}
	categoryIds, err := svc.categorySvc.GetChatroomCategoryIds(ctx, chatroom.Category)
	if err != nil {
		_ = svc.logger.Log("err", err)
	}
	messageCount7, err := svc.repo.MessageCount7(context.Background(), id)
	if err != nil {
		_ = svc.logger.Log("get chatroom message count 7 error:", err)
	}
	memberCount, err := svc.repo.MemberCount(context.Background(), id)
	if err != nil {
		_ = svc.logger.Log("get chatroom member count 7 error:", err)
	}
	count := &ChatroomCount{MessageCount7: messageCount7,
		MemberCount: memberCount}
	var resp *ChatroomCardResponse
	allMembers := make([]*MemberResponse, 0, len(chatroom.Members))
	for _, member := range chatroom.Members {
		memberes := &MemberResponse{
			Id:           member.Id,
			NickName:     member.NickName,
			Alias:        member.Aliases[0],
			MessageCount: member.MsgCount,
		}
		allMembers = append(allMembers, memberes)
	}
	resp = &ChatroomCardResponse{
		Id:            chatroom.Id,
		Name:          chatroom.Name,
		Owner:         &MemberResponse{Id: chatroom.Owner.Id, NickName: chatroom.Owner.NickName},
		Avatar:        chatroom.Avatar,
		User:          chatroom.User,
		DataSource:    chatroom.DataSource,
		Watched:       watched,
		Tags:          chatroom.Tags,
		Category:      categoryIds,
		Comment:       chatroom.Comment,
		UsedName:      chatroom.UsedName,
		Members:       allMembers,
		ChatroomCount: count,
	}
	return resp, nil
}

func (svc *defaultChatroomService) Detail(ctx context.Context, id, userId string) (*ChatroomDetailResponse, error) {
	chatroom, err := svc.repo.Get(context.Background(), id)
	if err != nil {
		return nil, err
	}
	chatroom, err = svc.repo.GetChatroomCollectors(ctx, id, chatroom)
	if err != nil {
		return nil, err
	}
	watched, err := svc.chatroomWatchRepository.GetChatroomWatchedStatus(ctx, id, userId)
	if err != nil {
		_ = svc.logger.Log("get chatroom watched error,chatroom id:", id)
	}
	categoryIds, err := svc.categorySvc.GetChatroomCategoryIds(ctx, chatroom.Category)
	if err != nil {
		_ = svc.logger.Log("err", err)
	}
	messageCount7, err := svc.repo.MessageCount7(context.Background(), id)
	if err != nil {
		_ = svc.logger.Log("get chatroom message count 7 error:", err)
	}
	memberCount, err := svc.repo.MemberCount(context.Background(), id)
	if err != nil {
		_ = svc.logger.Log("get chatroom member count 7 error:", err)
	}
	lastMsgTimestamp, err := svc.repo.LastMessageTimestamp(ctx, id)
	if err != nil {
		_ = svc.logger.Log("get chatroom last message error:", err)
	}
	alarmCount, err := svc.repo.AlarmMessageCount7(ctx, id)
	if err != nil {
		_ = svc.logger.Log("get chatroom alarm message error:", err)
	}
	count := &ChatroomCount{MessageCount7: messageCount7,
		MemberCount:          memberCount,
		AlarmCount7:          alarmCount,
		LastMessageTimestamp: lastMsgTimestamp,
	}
	resp := &ChatroomDetailResponse{}
	allMembers := make([]*MemberResponse, 0, len(chatroom.Members))
	for _, member := range chatroom.Members {
		memberes := &MemberResponse{
			Id:           member.Id,
			NickName:     member.NickName,
			Alias:        member.Aliases[0],
			JoinMethod:   member.JoinMethod,
			Inviter:      &MemberResponse{Id: member.Inviter.Id, NickName: member.Inviter.NickName},
			MessageCount: member.MsgCount,
		}
		allMembers = append(allMembers, memberes)
	}
	resp = &ChatroomDetailResponse{
		Id:               chatroom.Id,
		Name:             chatroom.Name,
		Owner:            &MemberResponse{Id: chatroom.Owner.Id, NickName: chatroom.Owner.NickName},
		Avatar:           chatroom.Avatar,
		Collectors:       chatroom.CollectorId,
		Users:            chatroom.User,
		CollectorOrgans:  chatroom.CollectorOrgan,
		CaptureTimestamp: chatroom.CaptureTimestamp,
		DataSource:       chatroom.DataSource,
		Watched:          watched,
		Tags:             chatroom.Tags,
		Category:         categoryIds,
		Comment:          chatroom.Comment,
		UsedName:         chatroom.UsedName,
		Members:          allMembers,
		ChatroomCount:    count,
	}
	return resp, nil
}

func NewChatroomService(repo ChatroomRepository, logger log.Logger,
	categoryService categories.CategoryService,
	watchRepository watch.WatchRepository) ChatroomService {
	return &defaultChatroomService{
		repo:                    repo,
		logger:                  logger,
		categorySvc:             categoryService,
		chatroomWatchRepository: watchRepository,
	}
}
